package com.quanyan.ic.task.job;

import com.alibaba.fastjson.JSON;
import com.github.ltsopensource.core.domain.Action;
import com.github.ltsopensource.tasktracker.Result;
import com.github.ltsopensource.tasktracker.runner.JobContext;
import com.github.ltsopensource.tasktracker.runner.JobRunner;
import com.quanyan.ic.cache.OrderMsgDao;
import com.quanyan.ic.cache.PlaceLightSettingDao;
import com.quanyan.ic.common.model.OrderMessage;
import com.quanyan.ic.model.FailedOrderMessage;
import com.quanyan.ic.model.PlaceLightSetting;
import com.quanyan.ic.protocol.LightCmd;
import com.quanyan.ic.protocol.codec.protobuf.ICMessageBuilder;
import com.quanyan.ic.protocol.server.LightServer;
import com.quanyan.ic.protocol.server.SendICMessageProcessor;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by zhuo.shi on 2017/6/5.
 * <p/>
 * 处理失败消息队列
 * 检查失败消息集合中是否有此客户端的消息，如果有，则重新下发
 */
@Component
public class FailedMsgCheckJob implements JobRunner {

    private static Logger logger = LoggerFactory.getLogger(FailedMsgCheckJob.class);

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private SendICMessageProcessor sendICMessageProcessor;
    @Autowired
    private OrderMsgDao orderMsgDao;
    @Autowired
    private PlaceLightSettingDao placeLightSettingDao;

    @Override
    public Result run(JobContext jobContext) throws Throwable {

        Map<String, Channel> sessionMap = LightServer.getSessionChannelMap();
        logger.info("--->sessionMap={}", sessionMap);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Set<String> placeIds = sessionMap.keySet();
        for (String _placeId : placeIds) {              //检查每个场馆的失败集合
            int placeId = Integer.valueOf(_placeId);
            Channel channel = sessionMap.get(String.valueOf(placeId));
            if (channel == null) {
                continue;
            }
            Map<Integer, List<FailedOrderMessage>> sitefList = orderMsgDao.findFailedOrderMsgSiteMap(placeId);
            PlaceLightSetting lightSetting = placeLightSettingDao.getLightControlSetting(placeId);
            if (lightSetting == null) {
                continue;
            }
            for (Integer siteId : sitefList.keySet()) {
                List<FailedOrderMessage> failedOrderMessageList = sitefList.get(siteId);
                if (failedOrderMessageList == null || failedOrderMessageList.size() == 0) {
                    continue;
                }
                boolean isTs = orderMsgDao.isOrderTimeSegmentIncludeBuffer(placeId, siteId,
                        lightSetting.getOn_light_before_order_start() * (60 * 1000L), lightSetting.getOff_light_after_order_end() * (60 * 1000L));  //当前时间，此场地是否有订单
                logger.info("placeId={}, siteId={}, failedMsgList={}, currentTime={}, isOrderTimeSegment={}", placeId, siteId, JSON.toJSONString(sitefList), sdf.format(new Date()), isTs);
                if (isTs) {
                    for (FailedOrderMessage f : failedOrderMessageList) {
                        if (f.getCmd().value() == LightCmd.ON.value()) {     //如果失败队列中有开指令
                            sendCmd(channel, f.getOrderMessage(), LightCmd.ON);
                            break;
                        }
                    }
                } else {
                    for (FailedOrderMessage f : failedOrderMessageList) {
                        if (f.getCmd().value() == LightCmd.OFF.value()) {     //如果失败队列中有关指令，下发关灯指令
                            sendCmd(channel, f.getOrderMessage(), LightCmd.OFF);
                            break;
                        }
                    }
                }
            }


//            Set<String> list = redisTemplate.opsForSet().members(RedisKey.buildSendFailedOrderMsgKey(placeId));
//            if (list == null || list.size() <= 0) {
//                logger.debug("placeId={}, failed orderMsg queue is empty", placeId);
//                continue;
//            }
//            logger.info("placeId={}, failedMsgList size: {}", placeId, list.size());
//
//            //目前上线自动灯光控制的场馆不多，订单已经结束的失败消息从队列中剔除
//            for (String value : list) {
//                OrderMessage orderMsg = JSON.parseObject(value, OrderMessage.class);


//                Long orderEndTime = orderMsg.getEndTime();
//                long currentTime = System.currentTimeMillis();
//                if (orderEndTime != null && orderEndTime <= currentTime) {      //订单已经过期
//                    redisTemplate.opsForSet().remove(RedisKey.buildSendFailedOrderMsgKey(placeId), value);
//                    logger.info("deleted failed orderMsg，currentTime>orderEndTime({}>{}), --> orderMsg={}", sdf.format(new Date(currentTime)), sdf.format(new Date(orderEndTime)), value);
//                }else {
//                    Integer pid = orderMsg.getPlaceId();
//                    if (pid != null && sessionMap.containsKey(String.valueOf(pid))) {
//                        Channel channel = sessionMap.get(String.valueOf(pid));
//                        logger.info("find the failed orderMsg {}, try to resend ", value);
//                        if (channel != null && channel.isActive()) {
//                            sendICMessageProcessor.sendICMessage(orderMsg, channel);
//                        }else {
//                            logger.warn("channel {} is un Active", (channel != null)?channel.remoteAddress():"");
//                        }
//                    }
//                }
//            }
        }
        return new Result(Action.EXECUTE_SUCCESS);
    }

    private void sendCmd(Channel channel, OrderMessage orderMessage, LightCmd cmd) {
        channel.writeAndFlush(ICMessageBuilder.buildBizICMessage(orderMessage, cmd));
        orderMsgDao.saveFailedChannelMsg(FailedOrderMessage.build(orderMessage, cmd));
        logger.info("try to resend {} cmd to client {}, orderMsg={}", cmd.value() == 0 ? "OFF" : "ON", channel.remoteAddress(), JSON.toJSONString(orderMessage));
    }
}
